package com.sc.commons.base.utils.except;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sc.commons.base.dto.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.MethodArgumentNotValidException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.validation.BindException ;
import java.util.UUID;


/**
 * @author
 */
@Slf4j
public class BaseExceptionProcess {


    /**
     * 处理异常核心类
     *
     * @param ex
     * @param o
     * @return
     */
    public static BaseResponse process(Throwable ex, Environment environment, ObjectMapper o, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
        if (ex instanceof ScException) {
            ScException sce = (ScException) ex;
            return printLog(sce, sce,environment, o, request, response);
        }

        if (ex instanceof BindException) {
            BindException e = (BindException)ex;
            ScException sce = new ScException(HttpServletResponse.SC_BAD_REQUEST,e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
            return printLog(sce, ex,environment, o, request, response);
        }

        if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException e = (MethodArgumentNotValidException)ex;
            ScException sce = new ScException(HttpServletResponse.SC_BAD_REQUEST,e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
            return printLog(sce, ex,environment, o, request, response);
        }

        ScException sce = new ScException(453,ex.getMessage());
        return printLog(sce, ex,environment, o, request, response);
    }

    private static BaseResponse printLog(ScException sce, Throwable ex, Environment environment, ObjectMapper o, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
        String url = request.getRequestURI().toString();
        String queryString = request.getQueryString();

        ControllerLog clog = new ControllerLog();

        clog.setGroupId(environment.getProperty("project.groupId"));
        clog.setArtifactId(environment.getProperty("project.artifactId"));
        clog.setVersion(environment.getProperty("project.version"));
        clog.setAuthor(environment.getProperty("project.author"));

        clog.setLogId(UUID.randomUUID().toString());

//        clog.setIp(getIp());
        clog.setPort(Integer.parseInt(environment.getProperty("local.server.port")));

        clog.setUrl(url);
        clog.setQueryString(queryString);


        if (ex instanceof BindException) {
            clog.setArgs(o.writeValueAsString(((BindException)ex).getBindingResult().getTarget()));
        } else if(ex instanceof MethodArgumentNotValidException){
            clog.setArgs(o.writeValueAsString(((MethodArgumentNotValidException)ex).getBindingResult().getTarget()));
        }

        Long l = (Long) request.getAttribute("mk_starTime");
        if(l == null){
            clog.setTime(-1L);
        } else {
            clog.setTime(System.currentTimeMillis() - l);
        }
        clog.setQueryString(queryString);
        clog.setCode(sce.getCode());
        log.debug("mk-log-stack:{}", o.writeValueAsString(clog));


        // --------------

        writeJsonAndState(sce, response);
        return BaseResponse.error(sce);
    }

    private static void writeJsonAndState(ScException sce, HttpServletResponse response) {
        response.setStatus(sce.getCode());
    }


}
